/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

#ifndef __QS_DataSerializer_H__
#define __QS_DataSerializer_H__

#include <string>
#include <vector>

namespace QSThink
{
	//simple data transfer protocal
	enum SerializeDataType
	{
		SerializeDataType_Bool,
		SerializeDataType__Int32,
		SerializeDataType__Float,
		SerializeDataType__Double,
		SerializeDataType__String,
		SerializeDataType__Bytes,//plain binary bytes

		//enum ObjectType  from engine
		SerializeDataType__ObjectType,
		
		
	};

	enum PersistenceType
	{
		PersistenceType_Unkown,

		
		//NOTE::Above sequence are fixed,New add just above here!!for we serialize data into disk.
	};
	
	class PersistenceDatagram
	{
	public:
		//header contains packet id(int) and packet body length(int)
		enum { HEADER_LENGTH = 8 };

		PersistenceDatagram(int count);
		PersistenceDatagram(char* data,int count);
		~PersistenceDatagram();
		int getId();
		char* data();
		int length();
		char* body();
		//decode header,get body length in bytes
		int getBodyLength();

		void write(int i);
		void write(float f);
		void write(char* buf,int count);

		bool readBool();
		int readInt();
		float readFloat();		
		double readDouble();
		std::string readString(int bytes);
		char* readBytes(int bytes);

	private:
		char* _data;
		int _pos;
		static int _count;//the count of datagrams produces
	};

	//parse srcp param
	class PersistenceDataParam
	{
	private:
		SerializeDataType _type;//the param type (INT,UTF8_STR,_data,...)
		char* _data;//for _data,all should convert to this
		int _count;

	public:
		PersistenceDataParam(bool b);
		PersistenceDataParam(int i);	
		PersistenceDataParam(float f);
		PersistenceDataParam(double d);
		PersistenceDataParam(std::string str);
		
		PersistenceDataParam(char* bytes,int count);
		~PersistenceDataParam();

		inline static bool isBoolParam(PersistenceDataParam* param)
		{
			if(param!=0){
				if(param->getParamType()==SerializeDataType_Bool){
					return true;
				}
			}
			return false;
		}

		inline static bool isIntParam(PersistenceDataParam* param)
		{
			if(param!=0){
				if(param->getParamType()==SerializeDataType__Int32){
					return true;
				}
			}
			return false;
		}

		inline static bool isFloatParam(PersistenceDataParam* param)
		{
			if(param!=0){
				if(param->getParamType()==SerializeDataType__Float){
					return true;
				}
			}
			return false;
		}

		inline static bool isStringParam(PersistenceDataParam* param)
		{
			if(param!=0){
				if(param->getParamType()==SerializeDataType__String){
					return true;
				}
			}
			return false;
		}

		
		SerializeDataType getParamType();
		int getByteCount();
		char* getData();
		
		bool getBool();
		int getInt();
		float getFloat();
		std::string getString();
		
	};

	typedef std::vector<PersistenceDataParam*> GDataParamList;

	class PersistenceDataParser
	{
	private:
		PersistenceType _name;
		std::vector<SerializeDataType> paramTypeList;
		std::vector<int> paramByteCountList;
		std::vector<PersistenceDataParam*> _paramList;
		int _paramCount;
		int _index;//read index
		PersistenceDatagram *_datagram;
		bool _success;//is parse success
	public:
		PersistenceType getName();
		PersistenceDataParam* getParam(int index);
		PersistenceDataParam* getParam();
		PersistenceDataParser(PersistenceDatagram* datagram);
		PersistenceDataParser(std::string fileName);
		~PersistenceDataParser();

		void parse();

		inline bool success()
		{
			return _success;
		}
	};

	class GDataGenerator
	{
	public:
		
	private:
		PersistenceType _name;
		std::vector<PersistenceDataParam*> _paramList;
		int _paramCount;

		int _length;
		PersistenceDatagram *_datagram;
	public:
		~GDataGenerator(void);

		GDataGenerator(PersistenceType name);
		void addBoolParam(bool b);
		void addIntParam(int i);
		void addFloatParam(float f);
		void addDoubleParam(double d);
		void addStringParam(std::string str);
		void addBytesParam(char *bytes,int count);

		PersistenceDatagram* genDatagram();

		void serialize(std::string fileName);
	};
}
#endif
